<?php
// +----------------------------------------------------------------------
// | ThinkPHP
// +----------------------------------------------------------------------
// | Copyright (c) 2008 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
// $Id$

// ORM 驱动类
class ORM extends Base implements IteratorAggregate{

    // 模型名称（不包含模型前后缀）
    public $name = '';
    // 数据表前缀
    protected $tablePrefix	=	'';
    // 数据表后缀
    protected $tableSuffix = '';
    // 数据表名（不包含表前后缀）
    protected $tableName = '';
    // 实际数据表名（包含表前后缀）
    protected $trueTableName = '';
    // 数据库连接对象列表
    protected $_db = array();
    // 当前数据库操作对象
    protected $db = null;
    // 字段信息
    protected $fields = array();
    // 字段类型信息
    protected $type	 =	 array();
    // 查询表达式参数
    protected $options	=	array();
    // 模型要返回的数据类型
    protected $dataType	=	null;

   /**
     +----------------------------------------------------------
     * 取得视图对象实例
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @return Template
     +----------------------------------------------------------
     */
    static function getInstance() {
        return Think::instance(__CLASS__);
    }

    public function __construct() {
        // 获取数据库操作对象
        Think::import("Think.Db.Db");
        if(!empty($this->connection)) {
            // 当前模型有独立的数据库连接信息
            $this->db = Db::getInstance($this->connection);
        }else{
            $this->db = Db::getInstance();
        }
        // 设置数据库的返回数据格式
        $this->db->resultType   =   $this->dataType?$this->dataType:C('DATA_RESULT_TYPE');
        // 设置默认的数据库连接
        $this->_db[0]   =   &$this->db;
        // 设置表前后缀
        $this->tablePrefix = C('DB_PREFIX')|'';
        $this->tableSuffix = C('DB_SUFFIX')|'';
        // 数据表字段检测
        $this->_checkTableInfo();
    }

    /**
     +----------------------------------------------------------
     * 得到主键名称
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @return string
     +----------------------------------------------------------
     */
    public function getPk() {
        return isset($this->fields['_pk'])?$this->fields['_pk']:'id';
    }

    /**
     +----------------------------------------------------------
     * 返回数据库字段信息
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @return string
     +----------------------------------------------------------
     */
    public function getDbFields(){
        return $this->fields;
    }

    /**
     +----------------------------------------------------------
     * 返回最后插入的ID
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @return string
     +----------------------------------------------------------
     */
    public function getLastInsID() {
        return $this->db->lastInsID;
    }

    /**
     +----------------------------------------------------------
     * 返回最后执行的sql语句
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @return string
     +----------------------------------------------------------
     */
    public function getLastSql() {
        return $this->db->getLastSql();
    }

    /**
     +----------------------------------------------------------
     * 获取Iterator因子
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @return Iterate
     +----------------------------------------------------------
     */
    public function getIterator()
    {
        if(!empty($this->dataList)) {
            // 存在数据集则返回数据集
            return new ArrayObject($this->dataList);
        }elseif(!empty($this->data)){
            // 存在数据对象则返回对象的Iterator
            return new ArrayObject($this->data);
        }else{
            // 否则返回字段名称的Iterator
            $fields = $this->fields;
            unset($fields['_pk'],$fields['_autoInc']);
            return new ArrayObject($fields);
        }
    }

    /**
     +----------------------------------------------------------
     * 设置数据对象的值
     +----------------------------------------------------------
     * @access protected
     +----------------------------------------------------------
     * @param string $name 名称
     * @param mixed $value 值
     +----------------------------------------------------------
     * @return void
     +----------------------------------------------------------
     */
    protected function __set($name,$value) {
        // 设置数据对象属性
        $this->data[$name]	=	$value;
    }

    /**
     +----------------------------------------------------------
     * 获取数据对象的值
     +----------------------------------------------------------
     * @access protected
     +----------------------------------------------------------
     * @param string $name 名称
     +----------------------------------------------------------
     * @return mixed
     +----------------------------------------------------------
     */
    protected function __get($name) {
        if(isset($this->data[$name])) {
            return $this->data[$name];
        }else{
            return null;
        }
    }

    /**
     +----------------------------------------------------------
     * 把数据对象转换成数组
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @return array
     +----------------------------------------------------------
     */
    public function toArray()
    {
        if(!empty($this->dataList)) {
            return $this->dataList;
        }elseif (!empty($this->data)){
            return $this->data;
        }
        return false;
    }

    /**
     +----------------------------------------------------------
     * 数据表字段检测 并自动缓存
     +----------------------------------------------------------
     * @access private
     +----------------------------------------------------------
     * @return boolean
     +----------------------------------------------------------
     */
    private function _checkTableInfo() {
        // 如果不是Model类 自动记录数据表信息
        // 只在第一次执行记录
        if(empty($this->fields) && strtolower(get_class($this))!='model') {
            // 如果数据表字段没有定义则自动获取
            if(C('DB_FIELDS_CACHE')) {
                $identify   =   $this->name.'_fields';
                $this->fields = Think::fastCache($identify);
                if(!$this->fields) {
                    $this->flush();
                }
            }else{
                // 每次都会读取数据表信息
                $this->flush();
            }
        }
    }

    /**
     +----------------------------------------------------------
     * 强制刷新数据表信息
     +----------------------------------------------------------
     * @access private
     +----------------------------------------------------------
     * @return void
     +----------------------------------------------------------
     */
    public function flush() {
        // 缓存不存在则查询数据表信息
        $fields =   $this->db->getFields($this->getTableName());
        $this->fields   =   array_keys($fields);
        $this->fields['_autoInc'] = false;
        foreach ($fields as $key=>$val){
            // 记录字段类型
            $this->type[$key]    =   $val['type'];
            if($val['primary']) {
                $this->fields['_pk']    =   $key;
                if($val['autoInc']) $this->fields['_autoInc']   =   true;
            }
        }
        if(C('DB_FIELDS_CACHE')) {
            $identify   =   $this->name.'_fields';
            // 永久缓存数据表信息
            Think::fastCache($identify,$this->fields);
        }
    }

    /**
     +----------------------------------------------------------
     * 增加数据库连接
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param mixed $config 数据库连接信息
     * 支持批量添加 例如 array(1=>$config1,2=>$config2)
     * @param mixed $linkNum  创建的连接序号
     +----------------------------------------------------------
     * @return boolean
     +----------------------------------------------------------
     */
    public function addConnect($config,$linkNum=NULL) {
        if(isset($this->_db[$linkNum])) {
            return false;
        }
        if(NULL === $linkNum && is_array($config)) {
            // 支持批量增加数据库连接
            foreach ($config as $key=>$val){
                $this->_db[$key]            =    Db::getInstance($val);
            }
            return true;
        }
        // 创建一个新的实例
        $this->_db[$linkNum]            =    Db::getInstance($config);
        return true;
    }

    /**
     +----------------------------------------------------------
     * 删除数据库连接
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param integer $linkNum  创建的连接序号
     +----------------------------------------------------------
     * @return boolean
     +----------------------------------------------------------
     */
    public function delConnect($linkNum) {
        if(isset($this->_db[$linkNum])) {
            unset($this->_db[$linkNum]);
            return true;
        }
        return false;
    }

    /**
     +----------------------------------------------------------
     * 切换数据库连接
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param integer $linkNum  创建的连接序号
     +----------------------------------------------------------
     * @return boolean
     +----------------------------------------------------------
     */
    public function switchConnect($linkNum) {
        if(isset($this->_db[$linkNum])) {
            // 在不同实例直接切换
            $this->db   =   $this->_db[$linkNum];
            return true;
        }else{
            return false;
        }
    }

    /**
     +----------------------------------------------------------
     * 得到完整的数据表名
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @return string
     +----------------------------------------------------------
     */
    public function getTableName()
    {
        if(empty($this->trueTableName)) {
            $tableName  = !empty($this->tablePrefix) ? $this->tablePrefix : '';
            $tableName .= $this->tableName?$this->tableName:$this->name;
            $tableName .= !empty($this->tableSuffix) ? $this->tableSuffix : '';
            $this->trueTableName    =   strtolower($tableName);
        }echo $this->name;
        return $this->trueTableName;
    }

    /**
     +----------------------------------------------------------
     * 设置完整的数据表名 可以用于动态切换
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @return void
     +----------------------------------------------------------
     */
    public function setTableName($tableName) {
        $this->trueTableName  =  $tableName;
    }

    /**
     +----------------------------------------------------------
     * 启动事务
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @return void
     +----------------------------------------------------------
     * @throws ThinkExecption
     +----------------------------------------------------------
     */
    public function startTrans()
    {
        $this->commit();
        $this->db->startTrans();
        return ;
    }

    /**
     +----------------------------------------------------------
     * 提交事务
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @return boolean
     +----------------------------------------------------------
     * @throws ThinkExecption
     +----------------------------------------------------------
     */
    public function commit()
    {
        return $this->db->commit();
    }

    /**
     +----------------------------------------------------------
     * 事务回滚
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @return boolean
     +----------------------------------------------------------
     * @throws ThinkExecption
     +----------------------------------------------------------
     */
    public function rollback()
    {
        return $this->db->rollback();
    }

    /**
     +----------------------------------------------------------
     * 对保存到数据库的数据对象进行处理
     * 统一使用数组方式到数据库中间层 facade字段支持
     +----------------------------------------------------------
     * @access protected
     +----------------------------------------------------------
     * @param mixed $data 要操作的数据
     +----------------------------------------------------------
     * @return boolean
     +----------------------------------------------------------
     */
    protected function _facade($data) {
        if($data instanceof HashMap){
            // Map对象转换为数组
            $data = $data->toArray();
        }elseif(is_object($data)) {
            $data    =   get_object_vars($data);
        }elseif(is_string($data)){
            parse_str($data,$data);
        }
        // 检查序列化字段
        if(!empty($this->serializeField)) {
            // 定义方式  $this->serializeField = array('ser'=>array('name','email'));
            foreach ($this->serializeField as $key=>$val){
                if(empty($data[$key])) {
                    $serialize  =   array();
                    foreach ($val as $name){
                        if(isset($data[$name])) {
                            $serialize[$name]   =   $data[$name];
                            unset($data[$name]);
                        }
                    }
                    $data[$key] =   serialize($serialize);
                }
            }
        }
        // 写入数据的时候检查需要过滤的数据字段
        // $_filter  =  array('field'=>array('fun1','fun2'));
        if(!empty($this->_filter)) {
            foreach ($this->_filter as $field=>$filter){
                if(isset($data[$field])) {
                    $fun              =  $filter[0];
                    $data[$field]   =  $fun($data[$field]);
                }
            }
        }
        // 检查字段映射
        if(isset($this->_map)) {
            foreach ($this->_map as $key=>$val){
                if(isset($data[$key])) {
                    $data[$val] =   $data[$key];
                    unset($data[$key]);
                }
            }
        }
        return $data;
    }

    /**
     +----------------------------------------------------------
     * 数据库Insert操作
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param array $data 要insert的数据
     * @param array $options 参数表达式
     * 例如 array('condition'=>'id=1','field'=>'id,name','order'=>'id desc')
     * 支持的索引包括 condition field table order limit group having lock
     +----------------------------------------------------------
     * @return false|integer
     +----------------------------------------------------------
     */
    public function add($data='',$options=array()) {
        if(method_exists($this,'_before_add')) {
            if(!$this->_before_add($data,$options))
                return false;
        }
        if(empty($data)) {
            if(!empty($this->options['data'])) {
                $data    =   $this->options['data'];
            }elseif(!empty($this->data)){
                $data    =   $this->data;
            }else{
                $this->error     =   L('_DATA_TYPE_INVALID_');
                return false;
            }
        }
        // 规范化数据
        $data    =   $this->_facade($data);
        if(empty($options) && !empty($this->options)){
            $options    =   $this->options;
            // 查询过后清空sql表达式组装 避免影响下次查询
            $this->options  =   array();
        }
        if(!isset($options['table'])) {
            $options['table']   =   $this->getTableName();
        }
        // 插入数据
        if(false === $result = $this->db->insert($data,$options)){
            // 数据库插入操作失败
            $this->error = L('_OPERATION_WRONG_');
            return false;
        }else {
            $insertId   =   $this->getLastInsID();
            //数据保存触发器
            if(method_exists($this,'_after_add')) {
                if($insertId && !isset($data[$this->getPk()])) {
                    $data[$this->getPk()]   =   $insertId;
                }
                $this->_after_add($data,$options);
            }
            //成功后返回插入ID
            return $insertId?    $insertId  :   $result;
        }
    }

    /**
     +----------------------------------------------------------
     * 数据库Select Insert操作
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param array $insertOptions insert参数 包括 field table
     * @param array $selectOptions 参数表达式
     * 例如 array('condition'=>'id=1','field'=>'id,name','order'=>'id desc')
     * 支持的索引包括 condition field table order limit group having lock
     +----------------------------------------------------------
     * @return false|integer
     +----------------------------------------------------------
     */
    public function selectInsert($insertOptions,$selectOptions) {
        if(!isset($insertOptions['table'])) {
            $insertOptions['table'] =   $this->getTableName();
        }
        // 插入数据
        if(false === $result = $this->db->selectInsert($insertOptions,$selectOptions)){
            // 数据库插入操作失败
            $this->error = L('_OPERATION_WRONG_');
            return false;
        }else {
            //成功后
            return $result;
        }
    }

    /**
     +----------------------------------------------------------
     * 数据库Update操作
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param array $data 要create的数据
     * @param array $options 更新参数表达式
     +----------------------------------------------------------
     * @return boolean
     +----------------------------------------------------------
     */
    public function save($data='',$options=array()) {
        if(method_exists($this,'_before_save')) {
            if(!$this->_before_save($data,$options))
                return false;
        }
        if(empty($data)) {
            if(!empty($this->options['data'])) {
                $data    =   $this->options['data'];
            }elseif(!empty($this->data)){
                $data    =   $this->data;
            }else{
                $this->error     =   L('_DATA_TYPE_INVALID_');
                return false;
            }
        }
        $data    =   $this->_facade($data);
        if(empty($options) && !empty($this->options)){
            $options    =   $this->options;
            // 查询过后清空sql表达式组装 避免影响下次查询
            $this->options  =   array();
        }
        if(!isset($options['table'])) {
            $options['table']   =   $this->getTableName();
        }
        if(empty($options['condition']) && isset($data[$this->getPk()])) {
            $options['condition']  = $this->getPk()."=".$data[$this->getPk()];
            unset($data[$this->getPk()]);
        }
        if(false === $this->db->update($data,$options)){
            $this->error = L('_OPERATION_WRONG_');
            return false;
        }else {
            //数据保存触发器
            if(method_exists($this,'_after_save')) {
                $this->_after_save($data,$options);
            }
            return true;
        }
    }

    /**
     +----------------------------------------------------------
     * 数据库Delete操作
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param array $options 删除参数
     +----------------------------------------------------------
     * @return boolean
     +----------------------------------------------------------
     */
    public function delete($options=array()) {
        if(preg_match('/^\d+(\,\d+)*$/',$options)) {
            // 如果是数字 直接使用deleteByIds
            return $this->deleteBy($this->getPk(),$options);
        }
        if(method_exists($this,'_before_delete')) {
            if(!$this->_before_delete($options))
                return false;
        }
        if(empty($options) && !empty($this->options)){
            $options    =   $this->options;
            // 查询过后清空sql表达式组装 避免影响下次查询
            $this->options  =   array();
        }
        if(!isset($options['table'])) {
            $options['table']   =   $this->getTableName();
        }
        if(empty($options) && !empty($this->data)) {
            $options['condition']   =   $this->getPk().'='.$this->data[$this->getPk()];
        }
        $result=    $this->db->delete($options);
        if(false === $result ){
            $this->error =  L('_OPERATION_WRONG_');
            return false;
        }else {
            //数据保存触发器
            if(method_exists($this,'_after_delete')) {
                $this->_after_delete($options);
            }
            // 返回删除记录个数
            return $result;
        }
    }

    /**
     +----------------------------------------------------------
     * 数据库查询操作 对返回数据不作处理
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param array $options 查询参数
     +----------------------------------------------------------
     * @return mixed
     +----------------------------------------------------------
     */
    public function select($options=array()) {
        if(empty($options) && !empty($this->options)) {
            $options    =   $this->options;
            // 查询过后清空sql表达式组装 避免影响下次查询
            $this->options  =   array();
        }
        if(method_exists($this,'_before_select')) {
            $options    =   $this->_before_select($options);
            if(!$options)   return false;
        }
        if(!isset($options['table'])) {
            $options['table']   =   $this->getTableName();
        }
        $rs =   $this->db->select($options);
        if($rs) {
            //数据查询触发器
            if(method_exists($this,'_after_select')) {
                $this->_after_select($options);
            }
        }
        return  $rs;
    }

    /**
     +----------------------------------------------------------
     * 查询SQL组装 where
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param mixed $where
     +----------------------------------------------------------
     * @return Model
     +----------------------------------------------------------
     */
    public function where($where) {
        $this->options['condition'] =   $where;
        return $this;
    }

    /**
     +----------------------------------------------------------
     * 查询SQL组装 order
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param string $order
     +----------------------------------------------------------
     * @return Model
     +----------------------------------------------------------
     */
    public function order($order) {
        $this->options['order'] =   $order;
        return $this;
    }

    /**
     +----------------------------------------------------------
     * 查询SQL组装 table
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param mixed $table
     +----------------------------------------------------------
     * @return Model
     +----------------------------------------------------------
     */
    public function table($table) {
        $this->options['table'] =   $table;
        return $this;
    }

    /**
     +----------------------------------------------------------
     * 查询SQL组装 group
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param string $group
     +----------------------------------------------------------
     * @return Model
     +----------------------------------------------------------
     */
    public function group($group) {
        $this->options['group'] =   $group;
        return $this;
    }

    /**
     +----------------------------------------------------------
     * 查询SQL组装 field
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param string $field
     +----------------------------------------------------------
     * @return Model
     +----------------------------------------------------------
     */
    public function field($field) {
        $this->options['field'] =   $field;
        return $this;
    }

    /**
     +----------------------------------------------------------
     * 查询SQL组装 limit
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param array $limit
     +----------------------------------------------------------
     * @return Model
     +----------------------------------------------------------
     */
    public function limit($limit) {
        $this->options['limit'] =   $limit;
        return $this;
    }

    /**
     +----------------------------------------------------------
     * 查询SQL组装 join
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param array $join
     +----------------------------------------------------------
     * @return Model
     +----------------------------------------------------------
     */
    public function join($join) {
        $this->options['join']  =   $join;
        return $this;
    }

    /**
     +----------------------------------------------------------
     * 查询SQL组装 having
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param string $having
     +----------------------------------------------------------
     * @return Model
     +----------------------------------------------------------
     */
    public function having($having) {
        $this->options['having']    =   $having;
        return $this;
    }

    /**
     +----------------------------------------------------------
     * 查询SQL组装 distinct
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param boolean $distinct
     +----------------------------------------------------------
     * @return Model
     +----------------------------------------------------------
     */
    public function distinct($distinct) {
        $this->options['distinct']  =   $distinct;
        return $this;
    }

    /**
     +----------------------------------------------------------
     * 查询SQL组装 惰性
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param boolean $lazy 惰性查询
     +----------------------------------------------------------
     * @return Model
     +----------------------------------------------------------
     */
    public function lazy($lazy) {
        $this->options['lazy']  =   $lazy;
        return $this;
    }

    /**
     +----------------------------------------------------------
     * 查询SQL组装lock
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param boolean $lock 是否锁定
     +----------------------------------------------------------
     * @return Model
     +----------------------------------------------------------
     */
    public function lock($lock) {
        $this->options['lock']  =   $lock;
        return $this;
    }

    /**
     +----------------------------------------------------------
     * 进行关联查询
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param boolean $lock 是否锁定
     +----------------------------------------------------------
     * @return Model
     +----------------------------------------------------------
     */
    public function relation($name) {
        $this->options['link']  =   $name;
        return $this;
    }

    /**
     +----------------------------------------------------------
     * 查询SQL组装
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param string $sql sql语句
     +----------------------------------------------------------
     * @return Model
     +----------------------------------------------------------
     */
    public function sql($sql) {
        $this->options['sql']   =   $sql;
        return $this;
    }

    /**
     +----------------------------------------------------------
     * 数据SQL组装
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param string $data 要插入或者保存的数据
     +----------------------------------------------------------
     * @return Model
     +----------------------------------------------------------
     */
    public function data($data) {
        $this->options['data']  =   $data;
        return $this;
    }

    /**
     +----------------------------------------------------------
     * 数据库查询操作 并自动对数据对象赋值
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param array $options 查询参数
     +----------------------------------------------------------
     * @return mixed
     +----------------------------------------------------------
     */
    public function findAll($options=array()) {
        if(is_string($options) && preg_match('/^\d+(\,\d+)+$/',$options)) {
            return $this->getByIds($options);
        }
        if(isset($options['sql'])) {
            $rs = $this->query($options['sql']);
        }else{
            $rs = $this->select($options);
        }
        if($rs) {
            if($rs instanceof  ResultIterator) {
                // 如果是延时查询返回的是ResultIterator对象
                return $rs;
            }
            // 检查序列化字段
            if(!empty($this->serializeField)) {
                foreach ($this->serializeField as $key=>$val){
                    foreach ($rs as $k=>$result){
                        if(isset($result[$key])) {
                            $serialize   =   unserialize($result[$key]);
                            foreach ($serialize as $name=>$value){
                                $result[$name]  =   $value;
                            }
                            unset($serialize,$result[$key]);
                            $rs[$k] =   $result;
                        }
                    }
                }
            }
            if(method_exists($this,'_after_findall')) {
                $rs =   $this->_after_findall($rs,$options);
            }
            // 判断数据过滤
            $this->filterListFields($rs);
            // 对数据对象自动编码转换
            $rs  =   auto_charset($rs,C('DB_CHARSET'),C('TEMPLATE_CHARSET'));
            $this->dataList =   $rs;
        }
        return $rs;
    }

    /**
     +----------------------------------------------------------
     * 数据库查询操作 自动赋值数据对象
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param array $options 查询参数
     +----------------------------------------------------------
     * @return mixed
     +----------------------------------------------------------
     */
    public function find($options=array()) {
        if(is_numeric($options)) {
            // 根据主键的值获取某个记录
            return $this->getBy($this->getPk(),$options);
        }elseif(preg_match('/^\d+(\,\d+)*$/',$options)) {
            // 根据主机的值获取多个记录
            $condition[$this->getPk()]  = array('IN',$options);
            $options['condition']  =  $condition;
            return $this->find($options);
        }
        if(isset($options['sql'])) {
            $rs = $this->query($options['sql']);
        }else{
            $rs = $this->select($options);
        }
        if($rs) {
            if($rs instanceof ResultIterator) {
                // 如果是延时查询返回的是ResultIterator对象
                $rs =   $rs->getIterator();
            }
            $result =   $rs[0];
            // 检查序列化字段
            if(!empty($this->serializeField)) {
                foreach ($this->serializeField as $key=>$val){
                    if(isset($result[$key])) {
                        $serialize   =   unserialize($result[$key]);
                        foreach ($serialize as $name=>$value){
                            $result[$name]  =   $value;
                        }
                        unset($serialize,$result[$key]);
                    }
                }
            }
            if(method_exists($this,'_after_find')) {
                $result =   $this->_after_find($result,$options);
            }
            // 判断数据过滤
            $this->filterFields($result);
            // 对数据对象自动编码转换
            $result  =   auto_charset($result,C('DB_CHARSET'),C('TEMPLATE_CHARSET'));
            $this->data =   (array)$result;
        }else{
            $result =   false;
        }
        return $result;
    }

    /**
     +----------------------------------------------------------
     * 随机获取数据表的数据
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param array $options 查询参数
     +----------------------------------------------------------
     * @return mixed
     +----------------------------------------------------------
     */
    public function rand($options=array()) {
        if(empty($options) && !empty($this->options)) {
            $options    =   $this->options;
            // 查询过后清空sql表达式组装 避免影响下次查询
            $this->options  =   array();
        }
        $field      =   isset($options['field'])?   $options['field']   :   '*';
        $where  =   isset($options['condition'])?   $options['condition']   : 1;
        $limit      =   isset($options['limit'])?   $options['limit']   : 1;
        $table      =   isset($options['table'])?   $options['table']:$this->getTableName();
        // 拼装查询SQL
        $sql    =   'SELECT '.$field.' FROM '.$table.'  WHERE '.
            $where.' AND
            id >= (SELECT
            floor(
            RAND() * ((SELECT
            MAX(id)
            FROM
            '.$table.')-(SELECT
            MIN(id)
            FROM
            '.$table.')) + (SELECT
            MIN(id)
            FROM
            '.$table.')))
            ORDER
            BY
            id
            LIMIT
            '.$limit;

        $rs = $this->query($sql);
        return $rs;
    }

    /**
     +----------------------------------------------------------
     * 执行Sql查询
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param string $sql SQL语句
     * @param array $options 查询参数
     +----------------------------------------------------------
     * @return mixed
     +----------------------------------------------------------
     */
    public function query($sql,$options=array()) {
        if(empty($sql)) return false;
        if(strpos($sql,'__TABLE__')) {
            $sql    =   str_replace('__TABLE__',$this->getTableName(),$sql);
        }
        $result =   $this->db->query($sql,$options);
        if($result) {
            $this->dataList =   $result;
        }
        return $result;
    }

    /**
     +----------------------------------------------------------
     * 执行SQL语句
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param string $sql  SQL指令
     +----------------------------------------------------------
     * @return false | integer
     +----------------------------------------------------------
     */
    public function execute($sql,$options=array()) {
        if(empty($sql)) return false;
        if(strpos($sql,'__TABLE__')) {
            $sql    =   str_replace('__TABLE__',$this->getTableName(),$sql);
        }
        return  $this->db->execute($sql,$options);
    }

    /**
     +----------------------------------------------------------
     * 根据某个字段得到一条记录
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param string $field 字段名称
     * @param mixed $value 字段的值
     * @param array $options 查询表达式
     +----------------------------------------------------------
     * @return mixed
     +----------------------------------------------------------
     * @throws ThinkExecption
     +----------------------------------------------------------
     */
    public function getBy($field,$value,$options=array())
    {
        if(empty($options)) {
            $options    =   $this->options;
        }
        $condition[$field]  =  $value;
        $options['condition']   =   $condition;
        return $this->find($options);
    }

    /**
     +----------------------------------------------------------
     * 根据id范围获取多个记录
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param mixed $ids id范围
     * @param string $options 查询表达式
     +----------------------------------------------------------
     * @return mixed
     +----------------------------------------------------------
     * @throws ThinkExecption
     +----------------------------------------------------------
     */
    public function getByIds($ids,$options=array()) {
        if(is_array($ids)) {
            $ids    =   implode(',',$ids);
        }
        if(empty($options)) {
            $options    =   $this->options;
        }
        $options['condition']   =   array($this->getPk(),array("IN",$ids));
        return $this->findAll($options);
    }

    /**
     +----------------------------------------------------------
     * 根据某个字段删除数据
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param string $field 字段名称
     * @param mixed $value 字段值
     * @param array $options 查询表达式
     +----------------------------------------------------------
     * @return boolen
     +----------------------------------------------------------
     */
    // 根据某个字段的值删除记录
    public function deleteBy($field,$value,$options=array()) {
        $condition[$field]  =  $value;
        $options['condition']   =   $condition;
        return $this->delete($options);
    }

    /**
     +----------------------------------------------------------
     * 根据某个字段得到多条记录
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param string $field 字段名称
     * @param mixed $value 字段的值
     * @param string $options 查询表达式
     +----------------------------------------------------------
     * @return mixed
     +----------------------------------------------------------
     * @throws ThinkExecption
     +----------------------------------------------------------
     */
    public function getAllBy($field,$value,$options=array())
    {
        if(empty($options)) {
            $options    =   $this->options;
        }
        $condition[$field]  =  $value;
        $options['condition']   =   $condition;
        return $this->findAll($options);
    }

    /**
     +----------------------------------------------------------
     * 查找前N个记录
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param integer $count 记录个数
     * @param array $options  查询表达式
     +----------------------------------------------------------
     * @return mixed
     +----------------------------------------------------------
     * @throws ThinkExecption
     +----------------------------------------------------------
     */
    public function topN($count,$options=array()) {
        if(empty($options)) {
            $options    =   $this->options;
        }
        $options['limit']   =   $count;
        return $this->findAll($options);
    }

    /**
     +----------------------------------------------------------
     * 获取查询结果中的某个字段值
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param mixed $rs  查询结果
     * @param string $field  字段名
     +----------------------------------------------------------
     * @return mixed
     +----------------------------------------------------------
     * @throws ThinkExecption
     +----------------------------------------------------------
     */
    public function getCol($rs,$field)
    {
        if(!empty($rs)) {
            $result =   $rs[0];
            $field  =   is_array($result)?$result[$field]:$result->$field;
            return $field;
        }else {
            return null;
        }
    }

    /**
     +----------------------------------------------------------
     * 获取查询结果中的多个字段值
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param mixed $rs  查询结果
     * @param string $field  字段名用逗号分割多个
     * @param string $spea  多字段分割符号
     +----------------------------------------------------------
     * @return mixed
     +----------------------------------------------------------
     * @throws ThinkExecption
     +----------------------------------------------------------
     */
    public function getCols($rs,$field,$sepa=' ') {
        if(!empty($rs)) {
            $field  =   explode(',',$field);
            $cols    =   array();
            $length  = count($field);
            foreach ($rs as $result){
                if(is_object($result)) $result  =   get_object_vars($result);
                if($length>1) {
                    $cols[$result[$field[0]]]   =   '';
                    for($i=1; $i<$length; $i++) {
                        if($i+1<$length){
                            $cols[$result[$field[0]]] .= $result[$field[$i]].$sepa;
                        }else{
                            $cols[$result[$field[0]]] .= $result[$field[$i]];
                        }
                    }
                }else{
                    $cols[]  =   $result[$field[0]];
                }
            }
            return $cols;
        }
        return null;
    }

    /**
     +----------------------------------------------------------
     * 获取一条记录的某个字段值
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param string $field  字段名
     * @param mixed $condition  查询条件
     +----------------------------------------------------------
     * @return mixed
     +----------------------------------------------------------
     * @throws ThinkExecption
     +----------------------------------------------------------
     */
    public function getField($field='',$condition='',$as='')
    {
        if(!empty($this->options)) {
            $options    =   $this->options;
            // 查询过后清空sql表达式组装 避免影响下次查询
            $this->options  =   array();
        }
        if(!isset($options['field'])) {
            $options['field']    =   $field;
        }
        if(!isset($options['condition'])) {
            $options['condition']    =   $condition;
        }
        if(!isset($options['table'])) {
            $options['table']   =   $this->getTableName();
        }
        if(empty($as)) {
            $as =   $field;
        }
        $rs = $this->db->select($options);
        return $this->getCol($rs,$as);
    }

    /**
     +----------------------------------------------------------
     * 获取数据集的个别字段值
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param string $field 字段名称
     * @param mixed $condition  条件
     * @param string $spea  多字段分割符号
     +----------------------------------------------------------
     * @return array
     +----------------------------------------------------------
     * @throws ThinkExecption
     +----------------------------------------------------------
     */
    public function getFields($field='',$condition='',$sepa='')
    {
        if(!empty($this->options)) {
            $options    =   $this->options;
            // 查询过后清空sql表达式组装 避免影响下次查询
            $this->options  =   array();
        }
        if(!isset($options['field'])) {
            $options['field']    =   $field;
        }
        if(!isset($options['condition'])) {
            $options['condition']    =   $condition;
        }
        if(!isset($options['table'])) {
            $options['table']   =   $this->getTableName();
        }
        $rs = $this->db->select($options);
        return $this->getCols($rs,$field,$sepa);
    }

    /**
     +----------------------------------------------------------
     * 设置记录的某个字段值
     * 支持使用数据库字段和方法
     * 例如 setField('score','(score+1)',array('condition'=>'id=5'));
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param string $field  字段名
     * @param string $value  字段值
     * @param array $options 查询表达式
     +----------------------------------------------------------
     * @return boolean
     +----------------------------------------------------------
     * @throws ThinkExecption
     +----------------------------------------------------------
     */
    public function setField($field,$value,$options=array()) {
        if(empty($options) && !empty($this->options)) {
            $options    =   $this->options;
            // 查询过后清空sql表达式组装 避免影响下次查询
            $this->options  =   array();
        }
        if(!isset($options['table'])) {
            $options['table']   =   $this->getTableName();
        }
        return $this->db->setField($field,$value,$options);
    }

    /**
     +----------------------------------------------------------
     * 字段值增长
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param string $field  字段名
     * @param array $options 查询表达式
     * @param integer $step  增长值
     +----------------------------------------------------------
     * @return boolean
     +----------------------------------------------------------
     * @throws ThinkExecption
     +----------------------------------------------------------
     */
    public function setInc($field,$options=array(),$step=1) {
        if(empty($options) && !empty($this->options)) {
            $options    =   $this->options;
            // 查询过后清空sql表达式组装 避免影响下次查询
            $this->options  =   array();
        }
        if(!isset($options['table'])) {
            $options['table']   =   $this->getTableName();
        }
        return $this->db->setInc($field,$options,$step);
    }

    /**
     +----------------------------------------------------------
     * 字段值减少
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param string $field  字段名
     * @param array $options 查询表达式
     * @param integer $step  减少值
     +----------------------------------------------------------
     * @return boolean
     +----------------------------------------------------------
     * @throws ThinkExecption
     +----------------------------------------------------------
     */
    public function setDec($field,$options=array(),$step=1) {
        if(empty($options) && !empty($this->options)) {
            $options    =   $this->options;
            // 查询过后清空sql表达式组装 避免影响下次查询
            $this->options  =   array();
        }
        if(!isset($options['table'])) {
            $options['table']   =   $this->getTableName();
        }
        return $this->db->setDec($field,$options,$step);
    }

    /**
     +----------------------------------------------------------
     * 统计满足条件的记录个数
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param mixed $condition  条件
     * @param string $field  要统计的字段 默认为*
     +----------------------------------------------------------
     * @return integer
     +----------------------------------------------------------
     * @throws ThinkExecption
     +----------------------------------------------------------
     */
    public function count($condition='',$field='*')
    {
        return $this->getField('count('.$field.') as count',$condition,'count')|0;
    }

    /**
     +----------------------------------------------------------
     * 取得某个字段的最大值
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param string $field  字段名
     * @param mixed $condition  条件
     +----------------------------------------------------------
     * @return integer
     +----------------------------------------------------------
     * @throws ThinkExecption
     +----------------------------------------------------------
     */
    public function max($field,$condition='')
    {
        return floatval($this->getField('MAX('.$field.') as max',$condition,'max'));
    }

    /**
     +----------------------------------------------------------
     * 取得某个字段的最小值
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param string $field  字段名
     * @param mixed $condition  条件
     +----------------------------------------------------------
     * @return integer
     +----------------------------------------------------------
     * @throws ThinkExecption
     +----------------------------------------------------------
     */
    public function min($field,$condition='')
    {
        return floatval($this->getField('MIN('.$field.') as min',$condition,'min'));
    }

    /**
     +----------------------------------------------------------
     * 统计某个字段的总和
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param string $field  字段名
     * @param mixed $condition  条件
     +----------------------------------------------------------
     * @return integer
     +----------------------------------------------------------
     * @throws ThinkExecption
     +----------------------------------------------------------
     */
    public function sum($field,$condition='')
    {
        return floatval($this->getField('SUM('.$field.') as sum',$condition,'sum'));
    }

    /**
     +----------------------------------------------------------
     * 统计某个字段的平均值
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param string $field  字段名
     * @param mixed $condition  条件
     +----------------------------------------------------------
     * @return integer
     +----------------------------------------------------------
     * @throws ThinkExecption
     +----------------------------------------------------------
     */
    public function avg($field,$condition='')
    {
        return floatval($this->getField('AVG('.$field.') as avg',$condition,'avg'));
    }

    /**
     +----------------------------------------------------------
     * 查询符合条件的第N条记录
     * 0 表示第一条记录 -1 表示最后一条记录
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param integer $position 记录位置
     * @param array $options 查询表达式
     +----------------------------------------------------------
     * @return mixed
     +----------------------------------------------------------
     */
    public function getN($position=0,$options=array())
    {
        if($position>=0) {
            $options['limit']   =   $position.',1';
            $rs = $this->select($options);
            if($rs) {
                return $rs[0];
            }else{
                return false;
            }
        }else{
            $rs = $this->select($options);
            if($rs && count($rs)>=abs($position)) {
                return $rs[count($rs)-abs($position)];
            }else{
                return false;
            }
        }
    }

    /**
     +----------------------------------------------------------
     * 获取满足条件的第一条记录
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param array $options 查询表达式
     +----------------------------------------------------------
     * @return mixed
     +----------------------------------------------------------
     */
    public function first($options=array()) {
        return $this->getN(0,$options);
    }

    /**
     +----------------------------------------------------------
     * 获取满足条件的第后一条记录
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param array $options 查询表达式
     +----------------------------------------------------------
     * @return mixed
     +----------------------------------------------------------
     */
    public function last($options=array()) {
        return $this->getN(-1,$options);
    }

    /**
     +----------------------------------------------------------
     * 创建数据对象 但不保存到数据库
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param mixed $data 创建数据
     +----------------------------------------------------------
     * @return mixed
     +----------------------------------------------------------
     * @throws ThinkExecption
     +----------------------------------------------------------
     */
    public function create($data='')
    {
        // 如果没有传值默认取POST数据
        if(empty($data)) {
            $data    =   $_POST;
        }
        // 默认为新增模式
        $type    =   MODEL::MODEL_INSERT;
        $vo =   array();
        // 存在主键字段
        if(isset($data[$this->getPk()])) {
            if($this->getById($data[$this->getPk()])) {
                // 主键存在，改为更新数据模式
                $type    =   MODEL::MODEL_UPDATE;
            }
        }
        // 处理传递的数据
        $data    =   $this->_facade($data);

        // 创建数据对象之前进行数据验证
        if(!$this->autoValidation($data,$type)) {
            return false;
        }

        // 验证完成生成数据对象
        foreach ( $this->fields as $key=>$name){
            // 过滤特殊变量
            if(substr($key,0,1)=='_') continue;
            $val = isset($data[$name])?$data[$name]:null;
            //保证赋值有效
            if(!is_null($val) ){
                // 首先保证表单赋值
                $vo[$name] = MAGIC_QUOTES_GPC?   stripslashes($val)  :  $val;
            }elseif(    ($type == 'add' && in_array($name,$this->autoCreateTimestamps,true)) ||
            ($type == 'edit' && in_array($name,$this->autoUpdateTimestamps,true)) ){
                // 自动保存时间戳
                if(!empty($this->autoTimeFormat)) {
                    // 用指定日期格式记录时间戳
                    $vo[$name] =    date($this->autoTimeFormat);
                }else{
                    // 默认记录时间戳
                    $vo[$name] = time();
                }
            }
        }
        // 执行自动模型数据处理
        $vo =    $this->autoOperation($vo,$type);
        if($type == MODEL::MODEL_INSERT && !$this->fields['_autoInc'] && !isset($vo[$this->getPk()])) {
            // 如果主键不是自动增长类型 而且没有赋值 则写入GUID
            Think::import('Think.Util.String');
            $vo[$this->getPk()] =   String::keyGen();
        }

        // 赋值给数据对象
        $this->data =   $vo;

        if(DATA_TYPE_OBJ == $this->dataType) {
            // 对象模式 强制转换为stdClass对象实例
            $vo =   (object) $vo;
        }
        return $vo;
    }

    /**
     +----------------------------------------------------------
     * 自动表单处理
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param array $data 创建数据
     * @param string $type 创建类型
     +----------------------------------------------------------
     * @return mixed
     +----------------------------------------------------------
     * @throws ThinkExecption
     +----------------------------------------------------------
     */
    private function autoOperation(&$data,$type) {
        // 自动填充
        if(!empty($this->_auto)) {
            foreach ($this->_auto as $key=>$auto){
                // 填充因子定义格式
                // array('field','填充内容','附加规则','填充条件')
                //if(in_array($auto[0],$this->fields,true)) {
                    if(empty($auto[3])) $auto[3] = MODEL::MODEL_INSERT;// 默认为新增的时候自动填充
                    if( $type == $auto[3] || $auto[3] == MODEL::MODEL_BOTH)
                    {
                        switch($auto[2]) {
                            case 'function':    //  使用函数进行填充 字段的值作为参数
                                if(function_exists($auto[1])) {
                                    // 如果定义为函数则调用
                                    $data[$auto[0]] = $auto[1]($data[$auto[0]]);
                                }
                                break;
                            case 'field':    // 用其它字段的值进行填充
                                $data[$auto[0]] = $data[$auto[1]];
                                break;
                            case 'callback': // 使用回调方法
                                $data[$auto[0]]  =   $this->{$auto[1]}($data[$auto[0]]);
                                break;
                            case 'string':
                            default: // 默认作为字符串填充
                                $data[$auto[0]] = $auto[1];
                        }
                        if(false === $data[$auto[0]] ) {
                            unset($data[$auto[0]]);
                        }
                    }
                //}
            }
        }
        return $data;
    }

    /**
     +----------------------------------------------------------
     * 自动表单验证
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param array $data 创建数据
     * @param string $type 创建类型
     +----------------------------------------------------------
     * @return boolean
     +----------------------------------------------------------
     * @throws ThinkExecption
     +----------------------------------------------------------
     */
    private function autoValidation($data,$type) {
        // 属性验证
        if(!empty($this->_validate)) {
            // 如果设置了数据自动验证
            // 则进行数据验证
            foreach($this->_validate as $key=>$val) {
                // 验证因子定义格式
                // array(field,rule,message,condition,append,when)
                // field rule message 必须
                // condition 验证条件：EXISTS_VAILIDATE 存在字段就验证 MUST_VALIDATE 必须验证 VALUE_VAILIDATE 值不为空的时候验证 默认为EXISTS_VAILIDATE
                // append 附加规则 :function confirm regex equal in unique 默认为regex
                // when 验证时间: MODEL_BOTH MODEL_INSERT MODEL_UPDATE 默认为MODEL_BOTH
                // 判断是否需要执行验证
                if(empty($val[5]) || $val[5]== MODEL::MODEL_BOTH || $val[5] == $type ) {
                    // 判断验证条件
                    switch($val[3]) {
                        case MODEL::MUST_VALIDATE:    // 必须验证 不管表单是否有设置该字段
                            if(!$this->_validationField($data,$val)){
                                $this->error    =   $val[2];
                                return false;
                            }
                            break;
                        case MODEL::VALUE_VAILIDATE: // 值不为空的时候才验证
                            if('' != trim($data[$val[0]])){
                                if(!$this->_validationField($data,$val)){
                                    $this->error    =   $val[2];
                                    return false;
                                }
                            }
                            break;
                        case MODEL::EXISTS_VAILIDATE:
                        default:    // 默认表单存在该字段就验证
                            if(isset($data[$val[0]])){
                                if(!$this->_validationField($data,$val)){
                                    $this->error    =   $val[2];
                                    return false;
                                }
                            }
                    }
                }
            }
        }
        // TODO 数据类型验证
        //  判断数据类型是否符合
        return true;
    }

    /**
     +----------------------------------------------------------
     * 根据验证因子验证字段
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param array $data 创建数据
     * @param string $val 验证规则
     +----------------------------------------------------------
     * @return boolean
     +----------------------------------------------------------
     * @throws ThinkExecption
     +----------------------------------------------------------
     */
    private function _validationField($data,$val) {
        // 检查附加规则
        switch($val[4]) {
            case 'function':// 使用函数进行验证
                if(function_exists($val[1]) && !$val[1]($data[$val[0]])) {
                    return false;
                }
                break;
            case 'callback':// 调用方法进行验证
                if(!$this->{$val[1]}($data[$val[0]])) {
                    return false;
                }
                break;
            case 'confirm': // 验证两个字段是否相同
                if($data[$val[0]] != $data[$val[1]] ) {
                    return false;
                }
                break;
            case 'in': // 验证是否在某个数组范围之内
                if(!in_array($data[$val[0]] ,$data[$val[1]]) ) {
                    return false;
                }
                break;
            case 'equal': // 验证是否等于某个值
                if($data[$val[0]] != $val[1]) {
                    return false;
                }
                break;
            case 'unique': // 验证某个值是否唯一
                if(is_string($val[0]) && strpos($val[0],',')) {
                    $val[0]  =  explode(',',$val[0]);
                }
                if(is_array($val[0])) {
                    // 支持多个字段验证
                    $map = array();
                    foreach ($val[0] as $field){
                        $map[$field]   =  $data[$field];
                    }
                    if($this->find($map)) {
                        return false;
                    }
                }else{
                    if($this->getBy($val[0],$data[$val[0]])) {
                        return false;
                    }
                }
                break;
            case 'regex':
                default:    // 默认使用正则验证 可以使用验证类中定义的验证名称
                if( !Think::validate($data[$val[0]],$val[1])) {
                    return false;
                }
        }
        return true;
    }

    /**
     +----------------------------------------------------------
     * 得到分表的的数据表名
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param array $data 操作的数据
     +----------------------------------------------------------
     * @return string
     +----------------------------------------------------------
     */
    public function getPartitionTableName($data=array()) {
        if($data instanceof HashMap){
            // Map对象转换为数组
            $data = $data->toArray();
        }elseif(is_object($data)) {
            $data    =   get_object_vars($data);
        }elseif(is_string($data)){
            parse_str($data,$data);
        }
        // 对数据表进行分区
        if(isset($data[$this->partition['field']])) {
            $field   =   $data[$this->partition['field']];
            switch($this->partition['type']) {
                case 'id':
                    // 按照id范围分表
                    $step    =   $this->partition['expr'];
                    $seq    =   floor($field / $step)+1;
                    break;
                case 'year':
                    // 按照年份分表
                    if(!is_numeric($field)) {
                        $field   =   strtotime($field);
                    }
                    $seq    =   date('Y',$field)-$this->partition['expr']+1;
                    break;
                case 'mod':
                    // 按照id的模数分表
                    $seq    =   ($field % $this->partition['num'])+1;
                    break;
                case 'md5':
                    // 按照md5的序列分表
                    $seq    =   (ord(substr(md5($field),0,1)) % $this->partition['num'])+1;
                    break;
                default :
                    if(function_exists($this->partition['type'])) {
                        // 支持指定函数哈希
                        $fun    =   $this->partition['type'];
                        $seq    =   (ord(substr($fun($field),0,1)) % $this->partition['num'])+1;
                    }else{
                        // 按照字段的首字母的值分表
                        $seq    =   (ord($field{0}) % $this->partition['num'])+1;
                    }
            }
            return $this->getTableName().'_'.$seq;
        }else{
            // 当设置的分表字段不在查询条件或者数据中
            // 进行联合查询，必须设定 partition['num']
            $tableName  =   array();
            for($i=0;$i<$this->partition['num'];$i++) {
                $tableName[] = 'SELECT * FROM '.$this->getTableName().'_'.$i;
            }
            $tableName = '( '.implode(" UNION ",$tableName).') AS '.$this->getModelName();
            return $tableName;
        }
    }

}
?>